using System;
using Unity.Collections;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 与Content的相对关系
/// </summary>
public enum enRelationshipContent
{ 
    /// <summary>
    /// 视图内
    /// </summary>
    InView = 0,
    /// <summary>
    /// 超出视图左或上侧
    /// </summary>
    OutViewLeftOrTop,
    /// <summary>
    /// 超出视图右或下侧
    /// </summary>
    OutViewRightOrBottom,
    /// <summary>
    /// 左或上侧相交
    /// </summary>
    IntersectLeftOrTop,
    /// <summary>
    /// 右或下侧相交
    /// </summary>
    IntersectRightOrBottom,
}

/// <summary>
/// 滚动视图子项
/// </summary>
public class SFUI_ScrollRectItem : SFUI_Behaviour
{
    /// <summary>
    /// 数据索引
    /// </summary>
    public int dataIdx { get; private set; }
    /// <summary>
    /// 编号索引
    /// </summary>
    public int orderIdx { get; private set; }
    /// <summary>
    /// 模板InstanceId
    /// </summary>
    public int templeteGameObjectInstanceId { get; private set; }
    /// <summary>
    /// 绑定的ISimulateBehaviour
    /// </summary>
    public ISimulateBehaviour simulateBehaviour { get; private set; }
    /// <summary>
    /// ScrollRect
    /// </summary>
    public SFUI_ScrollRect ownerScrollRect { get; private set; }

    /// <summary>
    /// 设置模版参数
    /// </summary>
    /// <param name="_templeteGameObjectInstanceId">模板GameObject.GetInstanceID</param>
    /// <param name="_ownerScrollRect">所属ScrollRect</param>
    /// <param name="_simulateBehaviour">所属模拟行为脚本</param>
    public void SetTempleteArgs(int _templeteGameObjectInstanceId, SFUI_ScrollRect _ownerScrollRect, ISimulateBehaviour _simulateBehaviour)
    {
        templeteGameObjectInstanceId = _templeteGameObjectInstanceId;
        ownerScrollRect = _ownerScrollRect;
        simulateBehaviour = _simulateBehaviour;
    }

    /// <summary>
    /// 是否首部对齐
    /// </summary>
    /// <param name="_alignmentRowOrColumnCount">对齐行或列数量</param>
    /// <returns>true:是,false:否</returns>
    public bool IsFirstAlignment(int _alignmentRowOrColumnCount)
    {
        return (orderIdx % _alignmentRowOrColumnCount) == 0;
    }

    /// <summary>
    /// 首部对齐补齐数
    /// </summary>
    /// <param name="_alignmentRowOrColumnCount">对齐行或列数量</param>
    /// <returns>补齐数</returns>
    public int FirstAlignmentSupplement(int _alignmentRowOrColumnCount)
    {
        return orderIdx % _alignmentRowOrColumnCount;
    }

    /// <summary>
    /// 是否尾部对齐
    /// </summary>
    /// <param name="_alignmentRowOrColumnCount">对齐行或列数量</param>
    /// <returns>true:是,false:否</returns>
    public bool IsLastAlignment(int _alignmentRowOrColumnCount)
    {
        return (orderIdx % _alignmentRowOrColumnCount) == (_alignmentRowOrColumnCount - 1);
    }

    /// <summary>
    /// 尾部对齐补齐数
    /// </summary>
    /// <param name="_alignmentRowOrColumnCount">对齐行或列数量</param>
    /// <returns>补齐数</returns>
    public int LastAlignmentSupplement(int _alignmentRowOrColumnCount)
    {
        return _alignmentRowOrColumnCount - 1 - (orderIdx % _alignmentRowOrColumnCount);
    }

    /// <summary>
    /// Item的坐标偏移
    /// </summary>
    /// <returns>坐标偏移</returns>
    public Vector2 GetItemPivot()
    {
        Vector2 itemPivot = Text.GetTextAnchorPivot(TextAnchor.UpperLeft);
        itemPivot = itemPivot - rectTransform.pivot;
        itemPivot.x *= rectTransform.rect.width;
        itemPivot.y *= rectTransform.rect.height;
        itemPivot += rectTransform.anchoredPosition;
        return itemPivot;
    }

    /// <summary>
    /// content坐标偏移
    /// </summary>
    /// <returns>坐标偏移</returns>
    public Vector2 GetContentPivot()
    {
        Vector2 contentPivot = Text.GetTextAnchorPivot(TextAnchor.UpperLeft);
        contentPivot = contentPivot - ownerScrollRect.content.pivot;
        contentPivot.x *= ownerScrollRect.content.rect.width;
        contentPivot.y *= ownerScrollRect.content.rect.height;
        return contentPivot;
    }

    /// <summary>
    /// 靠左或右侧定位位置
    /// </summary>
    /// <returns>相对关系</returns>
    public Vector2 LocationLeftOrTopContentAnchoredPosition()
    {
        Vector2 anchoredPosition = Vector2.zero;
        Vector2 itemPivot = GetItemPivot();
        Vector2 contentPivot = GetContentPivot();

        Vector2 bounds = Vector2.zero;

        switch (ownerScrollRect.scrollMode)
        {
            case enSFUI_ScrollRect_ScrollMode.Horizontal:
                //Horizontal判定
                //左侧
                bounds.x = itemPivot.x + ownerScrollRect.content.anchoredPosition.x + contentPivot.x;
                //右侧
                bounds.y = bounds.x + rectTransform.rect.width + ownerScrollRect.spacing.x;
                if (bounds.y > ownerScrollRect.viewport.rect.width * 0.5f && rectTransform.rect.width * 2 < ownerScrollRect.viewport.rect.width)
                {
                    anchoredPosition.x = ownerScrollRect.viewport.rect.width - ownerScrollRect.content.rect.width;
                }
                else
                { 
                    
                }
                //bounds.x = itemPivot.x + ownerScrollRect.content.anchoredPosition.x + contentPivot.x;
                //bounds.y = bounds.x + rectTransform.rect.width + ownerScrollRect.spacing.x;
                //if (left < 0 && right < 0)
                //{
                //    超出左侧
                //}
                //else if (left > ownerScrollRect.viewport.rect.width && right > ownerScrollRect.viewport.rect.width)
                //{
                //    超出右侧
                //}
                //else if (left < 0)
                //{
                //    左侧相交
                //}
                //else if (right > ownerScrollRect.viewport.rect.width)
                //{
                //    右侧相交
                //}
                break;
            case enSFUI_ScrollRect_ScrollMode.Vertical:
                //Vertical判定
                //上侧
                bounds.x = itemPivot.y + ownerScrollRect.content.anchoredPosition.y + contentPivot.y;
                //下侧
                bounds.y = bounds.x - rectTransform.rect.height - ownerScrollRect.spacing.y;
                if (Mathf.Abs(bounds.y) > ownerScrollRect.viewport.rect.height * 0.5f && rectTransform.rect.height * 2 < ownerScrollRect.viewport.rect.height)
                {
                    anchoredPosition.y = ownerScrollRect.content.rect.height - ownerScrollRect.viewport.rect.height;
                }
                else
                { 
                
                }
                //if (top > 0 && bottom > 0)
                //{
                //    超出上侧
                //}
                //else if (top < -ownerScrollRect.viewport.rect.height && bottom < -ownerScrollRect.viewport.rect.height)
                //{
                //    超出下侧
                //}
                //else if (top > 0)
                //{
                //    上侧相交
                //}
                //else if (bottom < -ownerScrollRect.viewport.rect.height)
                //{
                //    下侧相交
                //}
                break;
        }
        return anchoredPosition;
    }

    /// <summary>
    /// 是否可向尾部预加载
    /// </summary>
    /// <param name="_preNum">预加载数</param>
    /// <returns>true:可预加载,false:不可预加载</returns>
    public bool CanPreAddLast(int _preNum)
    {
        bool result = false;
        float ap = 0;
        Vector2 itemPivot = GetItemPivot();
        Vector2 contentPivot = GetContentPivot();
        switch (ownerScrollRect.scrollMode)
        {
            case enSFUI_ScrollRect_ScrollMode.Horizontal:
                //Horizontal判定
                //左侧
                ap = itemPivot.x + ownerScrollRect.content.anchoredPosition.x + contentPivot.x;
                //右侧
                ap = ap + rectTransform.rect.width + ownerScrollRect.spacing.x;
                result = (ap - ownerScrollRect.viewport.rect.width) < _preNum * rectTransform.rect.width;    
                break;
            case enSFUI_ScrollRect_ScrollMode.Vertical:
                //Vertical判定
                //上侧
                ap = itemPivot.y + ownerScrollRect.content.anchoredPosition.y + contentPivot.y;
                //下侧
                ap = ap - rectTransform.rect.height - ownerScrollRect.spacing.y;
                result = Mathf.Abs(ap) - ownerScrollRect.viewport.rect.height < _preNum * rectTransform.rect.height;
                break;
        }
        return result;
    }

    /// <summary>
    /// 是否可尾部回收
    /// </summary>
    /// <param name="_preNum">预加载数</param>
    /// <returns>true:可尾部回收，false:不可尾部回收</returns>
    public bool CanRecycleLast(int _preNum)
    {
        bool result = false;
        float ap = 0;
        Vector2 itemPivot = GetItemPivot();
        Vector2 contentPivot = GetContentPivot();
        _preNum+=2;
        switch (ownerScrollRect.scrollMode)
        {
            case enSFUI_ScrollRect_ScrollMode.Horizontal:
                //Horizontal判定
                //左侧
                ap = itemPivot.x + ownerScrollRect.content.anchoredPosition.x + contentPivot.x;
                //右侧
                ap = ap + rectTransform.rect.width + ownerScrollRect.spacing.x;
                result = (ap - ownerScrollRect.viewport.rect.width) > _preNum * rectTransform.rect.width;
                break;
            case enSFUI_ScrollRect_ScrollMode.Vertical:
                //Vertical判定
                //上侧
                ap = itemPivot.y + ownerScrollRect.content.anchoredPosition.y + contentPivot.y;
                //下侧
                ap = ap - rectTransform.rect.height - ownerScrollRect.spacing.y;
                result = Mathf.Abs(ap) - ownerScrollRect.viewport.rect.height > _preNum * rectTransform.rect.height;
                break;
        }
        return result;
    }

    /// <summary>
    /// 是否可向首部预加载
    /// </summary>
    /// <param name="_preNum">预加载数</param>
    /// <returns>true:可预加载,false:不可预加载</returns>
    public bool CanPreAddFirst(int _preNum)
    {
        bool result = false;
        float ap = 0;
        Vector2 itemPivot = GetItemPivot();
        Vector2 contentPivot = GetContentPivot();
        switch (ownerScrollRect.scrollMode)
        {
            case enSFUI_ScrollRect_ScrollMode.Horizontal:
                //Horizontal判定
                //左侧
                ap = itemPivot.x + ownerScrollRect.content.anchoredPosition.x + contentPivot.x;               
                result = Mathf.Abs(ap) < _preNum * rectTransform.rect.width;
                break;
            case enSFUI_ScrollRect_ScrollMode.Vertical:
                //Vertical判定
                //上侧
                ap = itemPivot.y + ownerScrollRect.content.anchoredPosition.y + contentPivot.y;             
                result = Mathf.Abs(ap) < _preNum * rectTransform.rect.height;
                break;
        }
        return result;
    }

    /// <summary>
    /// 是否可首部回收
    /// </summary>
    /// <param name="_preNum">预加载数</param>
    /// <returns>true:可首部回收，false:不可首部回收</returns>
    public bool CanRecycleFirst(int _preNum)
    {
        bool result = false;
        float ap = 0;
        Vector2 itemPivot = GetItemPivot();
        Vector2 contentPivot = GetContentPivot();
        _preNum += 2;
        switch (ownerScrollRect.scrollMode)
        {
            case enSFUI_ScrollRect_ScrollMode.Horizontal:
                //Horizontal判定
                //左侧
                ap = itemPivot.x + ownerScrollRect.content.anchoredPosition.x + contentPivot.x;
                result = Mathf.Abs(ap) > _preNum * rectTransform.rect.width;
                break;
            case enSFUI_ScrollRect_ScrollMode.Vertical:
                //Vertical判定
                //上侧
                ap = itemPivot.y + ownerScrollRect.content.anchoredPosition.y + contentPivot.y;
                result = Mathf.Abs(ap) > _preNum * rectTransform.rect.height;
                break;
        }
        return result;
    }

    /// <summary>
    /// 设置数据索引
    /// </summary>
    /// <param name="_dataIdx">数据索引</param>
    /// <param name="_orderIdx">编号索引</param>
    public void SetDataIndex(int _dataIdx, int _orderIdx)
    {
        dataIdx = _dataIdx;
        orderIdx = _orderIdx;
#if UNITY_EDITOR
        OnEditor_ResetName();
#endif
    }

#if UNITY_EDITOR
    /// <summary>
    /// 编辑器重置名称
    /// </summary>
    void OnEditor_ResetName()
    {
        gameObject.name = $" dataIdx:{dataIdx}_orderIdx:{orderIdx}_goId:{GetInstanceID()}_tempId:{templeteGameObjectInstanceId}";
    }
#endif
}
